using System;
using System.Collections.Generic;
using System.Text;

namespace BTreeSharp.Surfaces
{
    public class InMemorySurface:Surface
    {
        private byte[] buffer = new byte[0];
        private long position=0;
        public override void AllocateSpace(long bytes)
        {
            lock (this)
            {
                if (bytes < 0)
                    throw (new InvalidOperationException("Can't allocate a negative size buffer."));
                if (buffer.Length == 0)
                {
                    buffer = new byte[bytes];
                }
                else
                {
                    throw (new InvalidOperationException("Buffer is already allocated. Call ReallocateSpace instead"));
                }
            }
        }

        public override void ReallocateSpace(long newsize)
        {
            lock (this)
            {
                if (newsize < 0)
                    throw (new InvalidOperationException("Can't reallocate to a negative size."));
                byte[] old = buffer;
                buffer = new byte[newsize];
                Array.Copy(old, 0, buffer, 0, old.Length);
            }
        }

        public override byte[] ReadBytes(long size)
        {
            lock (this)
            {
                if (position + size >= Length)
                    throw new IndexOutOfRangeException(string.Format("Reading {0} bytes at position {1} is out of range", size, position));
                byte[] b = new byte[size];
                Array.Copy(buffer, position, b, 0, size);
                position += size;
                return b;
            }
        }

        public override void WriteBytes(byte[] bytes)
        {
            lock (this)
            {
                if (position + bytes.Length >= Length)
                    throw new IndexOutOfRangeException(string.Format("Writing {0} bytes at position {1} is out of range", bytes.Length, position));
                Array.Copy(bytes, 0, buffer, position, bytes.Length);
                position += bytes.Length;
            }
        }

        public override void Seek(long position, System.IO.SeekOrigin origin)
        {
            switch (origin)
            {
                case System.IO.SeekOrigin.Begin:
                    this.position = position;
                    break;
                case System.IO.SeekOrigin.Current:
                    this.position += position;
                    break;
                case System.IO.SeekOrigin.End:
                    this.position = this.Length - 1 + position;
                    break;
            }
        }

        public override long Length
        {
            get { return buffer.Length; }
        }

        public override long Position
        {
            get { return position; }
        }
    }
}
